package ar.uba.is2.common.mensaje.puerto.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;

import ar.uba.is2.common.mensaje.Mensaje;
import ar.uba.is2.common.mensaje.exception.EnviandoMensajeException;
import ar.uba.is2.common.mensaje.exception.LeyendoMensajeException;
import ar.uba.is2.common.mensaje.puerto.PuertoEntrada;
import ar.uba.is2.common.mensaje.puerto.PuertoSalida;

public class PuertoArchivo implements PuertoEntrada, PuertoSalida {

	private File salida;
	private BufferedReader in;
	
	public PuertoArchivo(File entrada, File salida) throws IOException {
		crearEntrada(entrada);
		this.salida = salida;
	}
	

	public void cerrar() {
		
		if (this.in != null){
			try {
				this.in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void enviarMensaje(Mensaje mensaje) throws EnviandoMensajeException {
		if (this.salida == null) {
			throw new UnsupportedOperationException("Este puerto no fue configurado para enviar mensajes");
		}
		Writer out = null;
		try {
			 out = crearSalida(this.salida);
			
			out.write(Mensaje.serializar(mensaje) + "\n");
			out.flush();
			
		} catch (IOException e) {
			throw new EnviandoMensajeException(e);
		} finally {
			if (out != null ) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}


	public Mensaje leerMensaje() throws LeyendoMensajeException {
		if (in == null) {
			throw new UnsupportedOperationException("Este puerto no fue configurado para recibir mensajes");
		}

		try {

			String line = null;
			synchronized (this) {
				while (line == null) {
					line = this.in.readLine();

					if (line == null) {
						this.wait(1000l);
					}
				}
			}
			Mensaje mensaje = Mensaje.deserializar(line);

			return mensaje;

		} catch (IOException e) {
			throw new LeyendoMensajeException(e);
		} catch (InterruptedException e) {
			throw new LeyendoMensajeException(e);
		} 
	}

	private void crearEntrada(File entrada) throws IOException, FileNotFoundException {
		if (entrada != null){
			
			if(entrada.exists()){
				// borro el archivo para que no entren mensajes viejos (i.e nadie puede escribirme si yo no existo)
				entrada.delete();
			}
			entrada.createNewFile();
			if (!entrada.canRead()){
				throw new IOException(String.format("No se puede leer el archivo %s",entrada.getPath()));
			}
			this.in = new BufferedReader(new InputStreamReader(new FileInputStream(entrada)));
		}
	}

	private Writer crearSalida(File salida) throws IOException, FileNotFoundException {

		if (salida != null) {
			if (!salida.exists()) {
				salida.createNewFile();
			}
			if (!salida.canWrite()) {
				throw new IOException(String.format("No se puede escribir el archivo %s",salida.getPath()));
			}
			return new OutputStreamWriter(new FileOutputStream(salida, true));
		}
		return null;
	}

}
